package dev.admin.service.base.impl;

import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import dev.admin.model.web.GridModel;
import dev.admin.service.base.LayuiService;
import dev.common.mapper.entity.Example;
import dev.common.mapper.util.Sqls;
import dev.common.service.impl.BaseService;
import dev.common.utils.StringUtils;
import dev.common.utils.WebUtils;
import org.apache.commons.beanutils.BeanMap;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @program: JoyDev
 * @description: Layui后台业务实现基类
 * @author: MR.C
 * @create: 2018-02-08 16:56
 **/
public abstract class LayuiServiceImpl<T> extends BaseService<T> implements LayuiService<T> {
    /**
     * @Description: 验证对象字段唯一
     * @Param: [t, property, title]
     * @return: boolean
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:32
     */
    protected boolean verifyUnique(T t, String property, String title) throws Exception {
        BeanMap beanMap = new BeanMap(t);
        Example example = new Example.Builder(getClazz()).where(Sqls.custom().andEqualTo(property, beanMap.get(property))).build();
        List<T> list = findByExample(example);
        if (list.size() > 1)
            throw new Exception("属性【" + property + "=" + beanMap.get(property) + "】存在多条数据：" + JSONObject.toJSON(list));
        if (list.size() == 0)
            return true;
        T t1 = list.get(0);
        BeanMap t1Map = new BeanMap(t1);
        if (null == t1 && beanMap.get("id").equals(t1Map.get("id")))
            return true;
        throw new Exception(title + "已存在");
    }

    /**
     * @Description: 获取layuiGridTable数据
     * @Param:
     * @return:
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:33
     */
    public GridModel getGridData(HttpServletRequest request) {
        Map<String, Object> paramMap = WebUtils.getParamMap(request);
        int limit = StringUtils.toInteger(paramMap.get("limit"));
        int page = StringUtils.toInteger(paramMap.get("page"));
        PageHelper.startPage(page, limit);
        List<T> list = findByParams(paramMap);
        return convertGridModel(new PageInfo<>(list));
    }

    @Override
    public int saveData(T t) throws Exception {
        if (!verifyData(t))
            return -1;
        insertCommonParam(t);
        return insert(t);
    }

    @Override
    public int updateData(T t) throws Exception {
        if (!verifyData(t))
            return -1;
        updateCommonParam(t);
        return updateByPrimaryKeySelective(t);
    }

    /**
     * @Description: 设置更新时间和更新人
     * @Param: [t]
     * @return: void
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:28
     */
    private void updateCommonParam(T t) throws Exception {
        Class<T> clazz = getClazz();
        Method setUpdateTime = clazz.getMethod("setUpdateTime", Date.class);
        if (null != setUpdateTime)
            setUpdateTime.invoke(t, new Date());
        Method setUpdateUser = clazz.getMethod("setUpdateUser", String.class);
        if (null != setUpdateUser)
            setUpdateUser.invoke(t, WebUtils.getCurrUser());
    }

    /**
     * @Description: 设置插入时间和插入人
     * @Param: [t]
     * @return: void
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:25
     */
    private void insertCommonParam(T t) throws Exception {
        Class<T> clazz = getClazz();
        Method setCreateTime = clazz.getMethod("setCreateTime", Date.class);
        if (null != setCreateTime)
            setCreateTime.invoke(t, new Date());
        Method setCreateUser = clazz.getMethod("setCreateUser", String.class);
        if (null != setCreateUser)
            setCreateUser.invoke(t, WebUtils.getCurrUser());
    }

    /**
     * @Description: 根据前端传入的查询条件查找，默认是单表查询，关联查询或者复杂查询请重写此方法
     * @Param: [paramMap]
     * @return: java.util.List<T>
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:30
     */
    private List<T> findByParams(Map<String, Object> paramMap) {
        return findByExample(getExample(paramMap));
    }

    /**
     * @Description: 封装layuiGrid所需数据
     * @Param: [pageInfo]
     * @return: dev.admin.model.web.GridModel
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:31
     */
    private GridModel convertGridModel(PageInfo<T> pageInfo) {
        GridModel model = new GridModel();
        model.setData(pageInfo.getList());
        model.setCount(pageInfo.getTotal());
        return model;
    }

    /**
     * @Description: 根据前台传入查询参数封装Example查询条件
     * @Param: [paramMap]
     * @return: dev.common.mapper.entity.Example
     * @Author: Mr.Chen
     * @Date: 2018/2/9 上午12:32
     */
    private Example getExample(Map<String, Object> paramMap) {
        Class<T> clazz = getClazz();
        Example example = new Example(clazz);
        Example.Criteria criteria = example.createCriteria();
        Set<String> keys = paramMap.keySet();
        if (!StringUtils.isNull(paramMap.get("field")))
            example.setOrderByClause(paramMap.get("field") + " " + paramMap.get("order"));
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            String name = declaredField.getName();
            if (!StringUtils.isNull(paramMap.get(name)))
                criteria.andEqualTo(name, paramMap.get(name));
            else if (!StringUtils.isNull(name + "_start"))
                criteria.andGreaterThanOrEqualTo(name, paramMap.get(name + "_start"));
            else if (!StringUtils.isNull(paramMap.get(name + "_end")))
                criteria.andLessThanOrEqualTo(name, paramMap.get(name + "_end"));
        }
        return example;
    }
}
